﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace Kokomo.IO
{
	[DebuggerDisplay("Base offset = {BaseOffset}")]
	public class StreamView : Stream
	{
		public Stream BaseStream { get; private set; }
		public long BaseOffset { get; private set; }

		private long _length;
		public override long Length { get { return this._length; } }

		public StreamView(Stream baseStream, long baseOffset, long length)
		{
			ArgumentValidation.CheckNullArgument("baseStream", baseStream);
			this.BaseStream = baseStream;
			this.BaseOffset = baseOffset;
			this._length = Length;
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			this.BaseStream.Dispose();
		}

		public override bool CanRead
		{
			get { return this.BaseStream.CanRead; }
		}

		public override bool CanSeek
		{
			get { return this.BaseStream.CanSeek; }
		}

		public override bool CanWrite
		{
			get { return this.BaseStream.CanWrite; }
		}

		public override void Flush()
		{
			this.BaseStream.Flush();
		}

		public override long Position
		{
			get
			{
				return this.BaseStream.Position - this.BaseOffset;
			}
			set
			{
				this.BaseStream.Position = value + this.BaseOffset;
			}
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return this.BaseStream.Read(buffer, offset, count);
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			long actualOffset = (origin == SeekOrigin.Current) ? offset : (offset + this.BaseOffset);
			
			return (this.BaseStream.Seek(actualOffset, origin) - this.BaseOffset);
		}

		public override void SetLength(long value)
		{
			throw new NotImplementedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			this.BaseStream.Write(buffer, offset, count);
		}
	}
}
